#include <stdio.h>
#include <string.h>
#include "infra_net.h"
#include "infra_defs.h"
#include "hal.h"


static int connect_tcp(utils_network_pt pNetwork)
{
    if (NULL == pNetwork) {
        HAL_Printf("network is null");
        return 1;
    }

    pNetwork->handle = HAL_TCP_Establish(pNetwork->pHostAddress, pNetwork->port);
    if (pNetwork->handle == (-1)) {
        return -1;
    }

    return 0;
}

int utils_net_connect(utils_network_pt pNetwork)
{
    int     ret = 0;
#ifdef SUPPORT_TLS
    if (NULL != pNetwork->ca_crt) {
        ret = connect_ssl(pNetwork);
    }
#else
    if (NULL == pNetwork->ca_crt) {
        ret = connect_tcp(pNetwork);
    }
#endif
    else {
        ret = -1;
        HAL_Printf("no method match!");
    }

    return ret;
}


static int read_tcp(utils_network_pt pNetwork, char *buffer, uint32_t len, uint32_t timeout_ms)
{
    return HAL_TCP_Read(pNetwork->handle, buffer, len, timeout_ms);
}


int utils_net_read(utils_network_pt pNetwork, char *buffer, uint32_t len, uint32_t timeout_ms)
{
    int     ret = 0;
#ifdef SUPPORT_TLS
    if (NULL != pNetwork->ca_crt) {
        ret = read_ssl(pNetwork, buffer, len, timeout_ms);
    }
#else
    if (NULL == pNetwork->ca_crt) {
        ret = read_tcp(pNetwork, buffer, len, timeout_ms);
    }
#endif
    else {
        ret = -1;
        HAL_Printf("no method match!");
    }

    return ret;
}


static int write_tcp(utils_network_pt pNetwork, const char *buffer, uint32_t len, uint32_t timeout_ms)
{
    return HAL_TCP_Write(pNetwork->handle, buffer, len, timeout_ms);
}


int utils_net_write(utils_network_pt pNetwork, const char *buffer, uint32_t len, uint32_t timeout_ms)
{
    int     ret = 0;
#ifdef SUPPORT_TLS
    if (NULL != pNetwork->ca_crt) {
        ret = write_ssl(pNetwork, buffer, len, timeout_ms);
    }
#else
    if (NULL == pNetwork->ca_crt) {
        ret = write_tcp(pNetwork, buffer, len, timeout_ms);
    }
#endif

    else {
        ret = -1;
        HAL_Printf("no method match!");
    }

    return ret;
}

static int disconnect_tcp(utils_network_pt pNetwork)
{
    if (pNetwork->handle == (-1)) {
        HAL_Printf("Network->handle = -1\n");
        return -1;
    }

    HAL_TCP_Destroy(pNetwork->handle);
    pNetwork->handle = (-1);
    return 0;
}

int utils_net_disconnect(utils_network_pt pNetwork)
{
    int     ret = 0;
#ifdef SUPPORT_TLS
    if (NULL != pNetwork->ca_crt) {
        ret = disconnect_ssl(pNetwork);
    }
#else
    if (NULL == pNetwork->ca_crt) {
        ret = disconnect_tcp(pNetwork);
    }
#endif
    else {
        ret = -1;
        HAL_Printf("no method match!");
    }

    return  ret;
}

int utils_net_init(utils_network_pt pNetwork, 
                const char *host, uint16_t port, const char *ca_crt, 
                const char *client_crt, const char *client_key, const char *client_pwd,
                const char *CN_hostname)
{
    if (!pNetwork || !host) {
        HAL_Printf("parameter error! pNetwork=%p, host = %p", pNetwork, host);
        return -1;
    }
    pNetwork->pHostAddress = host;
    pNetwork->port = port;
    pNetwork->ca_crt = ca_crt;

    if (NULL == ca_crt) {
        pNetwork->ca_crt_len = 0;
    } else {
        pNetwork->ca_crt_len = strlen(ca_crt);
    }

    pNetwork->client_crt = client_crt;
    if(NULL == client_crt){
        pNetwork->client_crt_len = 0;
    }else{
        pNetwork->client_crt_len = strlen(client_crt);
    }

    pNetwork->client_key = client_key;
    if(NULL == client_key){
        pNetwork->client_key_len = 0;
    }else{
        pNetwork->client_key_len = strlen(client_key);
    }

    pNetwork->client_pwd = client_pwd;
    if(NULL == client_pwd){
        pNetwork->client_pwd_len = 0;
    }else{
        pNetwork->client_pwd_len = strlen(client_pwd);
    }

    pNetwork->CN_hostname = CN_hostname;

    pNetwork->handle = 0;
    pNetwork->read = utils_net_read;
    pNetwork->write = utils_net_write;
    pNetwork->disconnect = utils_net_disconnect;
    pNetwork->connect = utils_net_connect;

    return 0;
}